#include "i2c.h"

__IO uint32_t  I2CTimeout = LH_I2C_LONG_TIMEOUT;

/**
 *@brief: I2C1初始化函数 PB6-SCL PB7-SDA
 */
void I2C1_Init(void){
    
    /* 使能时钟 */
    GPIO_InitTypeDef  GPIO_InitStructure;
     
    RCC_APB1PeriphClockCmd ( RCC_APB1Periph_I2C1 , ENABLE );
    RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOB, ENABLE );

    // PB6-SCL PB7-SDA
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;            // 开漏输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* I2C 配置 */
    I2C_InitTypeDef  I2C_InitStructure;

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 =I2C1_SLAVE_ADDRESS7;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = I2C1_Speed;
    I2C_Init(I2C1, &I2C_InitStructure);
    
    /* I2C 使能 */
    I2C_Cmd(I2C1, ENABLE);
    
    I2C_AcknowledgeConfig(I2C1,ENABLE);
}

/**
 *@brief: I2C通讯发生异常
 */
uint16_t LH_I2C_Error(I2C_TypeDef* I2Cx){
    if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)){
        I2C_GenerateSTOP(I2Cx,ENABLE);
    }
    return 1;
}

/**
 *@brief: I2C起始条件和从地址发送
 */
int16_t LH_I2C_Start(I2C_TypeDef* I2Cx,uint8_t address,uint8_t direction){
    
//    /*!< While the bus is not busy */
//    I2CTimeout = LH_I2C_LONG_TIMEOUT;
//    while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)){
//        if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
//    }
    
    //起始条件
    I2C_GenerateSTART(I2Cx,ENABLE);
    
     /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
    I2CTimeout = LH_I2C_FLAG_TIMEOUT;
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)){
        if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
    }
    
    //发送头地址
    I2C_Send7bitAddress(I2Cx, address, direction);
    
     /*!< Test on EV6 and clear it */
    I2CTimeout = LH_I2C_FLAG_TIMEOUT;
    if(I2C_Direction_Receiver){
        while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){
            if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
        }
    }else{
        while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){
            if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
        }
    }
    
    /* Read status register to clear ADDR flag */
	I2Cx->SR2;
    
    return 0;
}


/**
 *@brief: I2C写一个字节
 */
int16_t LH_I2C_WriteData(I2C_TypeDef* I2Cx,uint8_t data){
    
    /*!< Test on EV8 and clear it */
    I2CTimeout = LH_I2C_FLAG_TIMEOUT;
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)){
        if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
    }
    I2C_SendData(I2Cx,data);
    
    return 0;
}

/**
 *@brief: I2C结束条件
 */
int16_t LH_I2C_Stop(I2C_TypeDef* I2Cx){
    
    /*!< Test on EV8_2 and clear it */
    I2CTimeout = LH_I2C_FLAG_TIMEOUT;
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){
        if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
    }  
    
    I2C_GenerateSTOP(I2Cx,ENABLE);
    
    return 0;
}

/**
 *@brief: I2C读取数据并应答
 */
uint8_t LH_I2C_ReadWithAck(I2C_TypeDef* I2Cx) {
	uint8_t data;
	
	/* Enable ACK */
	I2C_AcknowledgeConfig(I2Cx,ENABLE);
	
	/* Wait till not received */
	I2CTimeout = LH_I2C_FLAG_TIMEOUT;
	while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
		if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
	}
	
	/* Read data */
	data = I2Cx->DR;
	
	/* Return data */
	return data;
}

/**
*@brief: I2C读取数据但不应答
 */
uint8_t LH_I2C_ReadWithNAck(I2C_TypeDef* I2Cx) {
	uint8_t data;
    
    /* Disable ACK */
	I2C_AcknowledgeConfig(I2Cx,DISABLE);
	/* Generate stop */
	I2C_GenerateSTOP(I2C1,ENABLE);
	
	/* Wait till received */
	I2CTimeout = LH_I2C_FLAG_TIMEOUT;
	while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
		if((I2CTimeout--) == 0) return ERROR_I2C_TIMEOUT;
	}

	/* Read data */
	data = I2C_ReceiveData(I2Cx);
    
    I2C_AcknowledgeConfig(I2Cx,ENABLE);
    
	/* Return data */
	return data;
}


/**
 *@brief: I2C 向从机寄存器写数据
 */
void LH_I2C_Write(I2C_TypeDef* I2Cx, uint8_t address, uint8_t reg, uint8_t data){
	LH_I2C_Start(I2Cx, address, I2C_Direction_Transmitter);
	LH_I2C_WriteData(I2Cx, reg);
    LH_I2C_WriteData(I2Cx, data);
	LH_I2C_Stop(I2Cx);
    
    if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)){
        I2C_GenerateSTOP(I2Cx,ENABLE);
    }
}

/**
 *@brief: I2C 向从机寄存器读数据
 */
uint8_t LH_I2C_Read(I2C_TypeDef* I2Cx, uint8_t address, uint8_t reg) {
	uint8_t received_data;
	LH_I2C_Start(I2Cx, address, I2C_Direction_Transmitter);
	LH_I2C_WriteData(I2Cx, reg);
	LH_I2C_Start(I2Cx, address, I2C_Direction_Receiver);
	received_data = LH_I2C_ReadWithNAck(I2Cx);  
	return received_data;
}

/**
 *@brief: I2C 向从机寄存器连续写
 */
void LH_I2C_WriteBuffer(I2C_TypeDef* I2Cx, uint8_t address, uint8_t reg, uint16_t length ,uint8_t* buffer) {
	LH_I2C_Start(I2Cx, address, I2C_Direction_Transmitter);
	LH_I2C_WriteData(I2Cx, reg);
	while (length--) {
		LH_I2C_WriteData(I2Cx, *buffer++);
//        if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)){
//            I2C_GenerateSTOP(I2Cx,ENABLE);
//            return;
//        }
	}
	LH_I2C_Stop(I2Cx);
    
    if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)){
        I2C_GenerateSTOP(I2Cx,ENABLE);
    }
}

/**
 *@brief: I2C 向从机寄存器连续读
 */
void LH_I2C_ReadBuffer(I2C_TypeDef* I2Cx, uint8_t address, uint8_t reg, uint16_t length, uint8_t* buffer) {
	LH_I2C_Start(I2Cx, address, I2C_Direction_Transmitter);
	LH_I2C_WriteData(I2Cx, reg);
	LH_I2C_Start(I2Cx, address, I2C_Direction_Receiver);
	while (length--) {
		if (!length) {
			*buffer++ = LH_I2C_ReadWithNAck(I2Cx);
		} else {
			*buffer++ = LH_I2C_ReadWithAck(I2Cx);
		}
	}
}

